package com.vhans.db.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vhans.core.domain.BQuiz;
import com.vhans.core.domain.BTagText;
import com.vhans.core.domain.BUserCollect;
import com.vhans.core.redis.RedisService;
import com.vhans.core.strategy.context.SearchStrategyContext;
import com.vhans.core.utils.BeanCopyUtils;
import com.vhans.core.utils.CommonUtils;
import com.vhans.core.utils.StringUtils;
import com.vhans.core.web.model.vo.QuizSearchVO;
import com.vhans.db.mapper.BQuizMapper;
import com.vhans.db.mapper.BTagMapper;
import com.vhans.db.mapper.BTagTextMapper;
import com.vhans.db.mapper.BUserCollectMapper;
import com.vhans.db.model.dto.ConditionDTO;
import com.vhans.db.model.dto.quiz.QuizDTO;
import com.vhans.db.model.vo.quiz.*;
import com.vhans.db.model.vo.tag.TagOptionVO;
import com.vhans.db.service.IAFileService;
import com.vhans.db.service.IBQuizService;
import com.vhans.db.service.IBTagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.vhans.core.constant.RedisConstant.QUIZ_LIKE_COUNT;
import static com.vhans.core.constant.RedisConstant.QUIZ_VIEW_COUNT;
import static com.vhans.core.enums.FilePathEnum.RECORDI;

/**
 * 题目业务处理
 *
 * @author vhans
 */
@Service
public class BQuizServiceImpl extends ServiceImpl<BQuizMapper, BQuiz> implements IBQuizService {

    @Autowired
    private BQuizMapper quizMapper;

    @Autowired
    private BTagTextMapper tagTextMapper;

    @Autowired
    private BTagMapper tagMapper;

    @Autowired
    private BUserCollectMapper userCollectMapper;

    @Autowired
    private IAFileService fileService;

    @Autowired
    private IBTagService tagService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SearchStrategyContext searchStrategyContext;

    @Override
    public List<QuizVO> listQuizVO(ConditionDTO condition) {
        // 查询题目信息
        List<QuizVO> quizVOList = quizMapper.selectQuizVO(condition);
        // 封装题目信息
        quizVOList.forEach(item -> {
            // 查询浏览量
            Double viewCount = Optional.ofNullable(redisService.getZsetScore(QUIZ_VIEW_COUNT, item.getId()))
                    .orElse((double) 0);
            // 查询点赞量
            Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, item.getId().toString());
            // 查询标签
            List<TagOptionVO> tags = Optional.ofNullable(tagMapper.selectTagByQuizId(item.getId())).orElse(new ArrayList<>());
            item.setViewCount(viewCount.intValue());
            // 设置当前点赞量为 持久点赞量 + 缓存点赞量
            item.setLikeNumber(item.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
            item.setTagVOList(tags);
        });
        return quizVOList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addQuiz(QuizDTO quiz) {
        // 添加题目
        BQuiz newQuiz = BeanCopyUtils.copyBean(quiz, BQuiz.class);
        newQuiz.setUserId(StpUtil.getLoginIdAsInt());
        baseMapper.insert(newQuiz);
        // 保存题目标签
        saveQuizTag(quiz, newQuiz.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteQuiz(List<Integer> quizIdList) {
        // 删除题目标签
        tagTextMapper.delete(new LambdaQueryWrapper<BTagText>()
                .in(BTagText::getTypeId, quizIdList));
        // 删除题目
        quizMapper.deleteBatchIds(quizIdList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateQuiz(QuizDTO quiz) {
        // 修改题目
        BQuiz newQuiz = BeanCopyUtils.copyBean(quiz, BQuiz.class);
        newQuiz.setUserId(StpUtil.getLoginIdAsInt());
        baseMapper.updateById(newQuiz);
        // 保存题目标签
        saveQuizTag(quiz, newQuiz.getId());
    }

    @Override
    public QuizInfoVO editQuiz(Integer quizId) {
        // 查询题目信息
        QuizInfoVO quizInfoVO = quizMapper.selectQuizInfoById(quizId);
        Assert.notNull(quizInfoVO, "没有该题目");
        // 转换图片格式
        if (StringUtils.isNotEmpty(quizInfoVO.getImages())) {
            quizInfoVO.setImgList(CommonUtils.castList(JSON.parseObject(quizInfoVO.getImages(), List.class), String.class));
        }
        // 查询题目标签名称
        List<String> tagNameList = tagMapper.selectTagNameByQuizId(quizId);
        quizInfoVO.setTagNameList(tagNameList);
        return quizInfoVO;
    }

    @Override
    public List<QuizSearchVO> listQuizSBySearch(String keyword) {
        return searchStrategyContext.executeQuizSearchStrategy(keyword);
    }

    @Override
    public List<QuizStudyListVO> listQuizStudyVO() {
        // 查询首页题目
        List<QuizStudyListVO> quizs = quizMapper.listQuizHomeVO();
        quizs.forEach(quiz -> {
            // 查询浏览量
            Double viewCount = Optional.ofNullable(redisService.getZsetScore(QUIZ_VIEW_COUNT, quiz.getId()))
                    .orElse((double) 0);
            // 查询点赞量
            Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, quiz.getId().toString());
            // 查询标签名
            List<String> tagNames = Optional.ofNullable(tagMapper.selectTagNameByQuizId(quiz.getId())).orElse(new ArrayList<>());
            quiz.setViewCount(viewCount.intValue());
            // 设置当前点赞量为 持久点赞量 + 缓存点赞量
            quiz.setLikeNumber(quiz.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
            quiz.setTagNameList(tagNames);
        });
        return quizs;
    }

    @Override
    public QuizStudyVO getQuizStudyById(Integer quizId) {
        // 查询题目信息
        QuizStudyVO quiz = quizMapper.selectQuizHomeById(quizId);
        if (StringUtils.isNull(quiz)) {
            return null;
        }
        // 转换图片格式
        if (StringUtils.isNotEmpty(quiz.getImages())) {
            quiz.setImgList(CommonUtils.castList(JSON.parseObject(quiz.getImages(), List.class), String.class));
        }
        // 浏览量+1
        redisService.incrZet(QUIZ_VIEW_COUNT, quizId, 1D);
        // 查询上一篇题目
        QuizPaginationVO lastQuiz = quizMapper.selectLastQuiz(quizId);
        // 查询下一篇题目
        QuizPaginationVO nextQuiz = quizMapper.selectNextQuiz(quizId);
        quiz.setLastQuiz(lastQuiz);
        quiz.setNextQuiz(nextQuiz);
        // 查询浏览量
        Double viewCount = Optional.ofNullable(redisService.getZsetScore(QUIZ_VIEW_COUNT, quizId))
                .orElse((double) 0);
        // 查询点赞量
        Integer likeNumber = redisService.getHash(QUIZ_LIKE_COUNT, quizId.toString());
        // 查询标签
        List<TagOptionVO> tags = Optional.ofNullable(tagMapper.selectTagByQuizId(quizId)).orElse(new ArrayList<>());
        quiz.setViewCount(viewCount.intValue());
        // 设置当前点赞量为 持久点赞量 + 缓存点赞量
        quiz.setLikeNumber(quiz.getLikeNumber() + Optional.ofNullable(likeNumber).orElse(0));
        quiz.setTagVOList(tags);
        return quiz;
    }

    @Override
    public List<QuizOverviewVO> listQuizOverviewVO() {
        return quizMapper.selectQuizList();
    }

    @Override
    public List<QuizRecommendVO> listQuizRecommendVO() {
        return quizMapper.selectQuizRecommend();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void collectQuiz(Integer quizId) {
        BQuiz quiz = quizMapper.selectOne(new LambdaQueryWrapper<BQuiz>()
                .eq(BQuiz::getId, quizId));
        Assert.notNull(quiz, "题目不存在");
        // 判断用户是否收藏
        List<Integer> collect = userCollectMapper.selectList(new LambdaQueryWrapper<BUserCollect>()
                        .select(BUserCollect::getUserId, BUserCollect::getTypeId)
                        .eq(BUserCollect::getUserId, StpUtil.getLoginIdAsInt()))
                .stream()
                .map(BUserCollect::getTypeId)
                .toList();
        if (collect.contains(quizId)) {
            // 取消收藏则删除用户的该收藏
            userCollectMapper.delete(new LambdaQueryWrapper<BUserCollect>()
                    .eq(BUserCollect::getUserId, StpUtil.getLoginIdAsInt())
                    .eq(BUserCollect::getTypeId, quizId));
            // 题目收藏数-1
            quiz.setCollectNumber(quiz.getCollectNumber() - 1);
        } else {
            // 收藏则添加用户的该收藏
            userCollectMapper.saveUserCollectQuiz(StpUtil.getLoginIdAsInt(), quizId);
            // 题目收藏数+1
            quiz.setCollectNumber(quiz.getCollectNumber() + 1);
        }
        quizMapper.updateById(quiz);
    }

    @Override
    public String saveQuizImages(MultipartFile file) {
        // 上传图片
        return fileService.uploadStrategyFile(file, RECORDI.getPath(), "image");
    }

    /**
     * 保存题目标签
     *
     * @param quiz   题目信息
     * @param quizId 题目id
     */
    private void saveQuizTag(QuizDTO quiz, Integer quizId) {
        // 删除题目标签
        tagTextMapper.delete(new LambdaQueryWrapper<BTagText>()
                .eq(BTagText::getTypeId, quizId));
        // 标签名列表
        List<String> tagNameList = quiz.getTagNameList();
        if (StringUtils.isNotEmpty(tagNameList)) {
            // 提供覆盖的标签
            List<Integer> coverTag = tagService.getCoverTag(tagNameList);
            // 将所有的标签绑定到题目标签关联表
            tagTextMapper.saveBatchQuizTag(quizId, coverTag);
        }
    }
}
